home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS03.ADF
/
C
/
error.c
< prev
next >
Wrap
Text File
|
1986-04-02
|
10KB
|
328 lines
/************************************************************************
* Error.c -- This program is intended to work with the Lattice C compiler.
*
* Copyright (c) 1986 by Scott Ballantyne.
* Free distribution encouraged, commercial sales of this
* program or source not allowed.
*
* Error's sole function in life is to merge a source listing
* with the error file generated by the first pass of the
* of the compiler (LC1). It will then enter ED, and ed will
* bring in the merged file.
* To use, first compile a file with LC1 as follows:
* LC1 >errorfile sourcefile.
* This will compile the source, and leave the errors in file
* errorfile. If you type LC1 >sourcefile.e sourcefile
* then when you run Error, the error file will be replaced
* with the contents of the merged file.
* Error will create a new file in the same directory as the
* source. The newfile will have a .e appended.
* If your source file was named file.c the merged file is
* called file.e
* Once the merge is completed, Error will run ED and ed will
* bring in your source.
* The error(s) appear directly before the line they reference.
* They are included as comments, so the source may be
* recompiled without having to delete the extra stuff.
* This program expects a file in the following format:
* 2 lines of header
* N lines of error messages consisting of
* sourcefile.c line_number message
* This format is the one currently generated by LC1.
* Compiling:
* Compile as usual, but linking with Astartup.obj will
* result in a much smaller file size. Recommended.
* Bugs: Bug in Execute() causes a small loss of memory.
*************************************************************************/
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#define PATH_SIZE 80 /* Just in case - for those long paths */
#define HEADER 2 /* Lines of copyright stuff to skip */
#define NO_MORE_LINES -1 /* Flag for end of file */
#define REST -2 /* NO_MORE_LINES - 1 */
#define NO_GO 0 /* AmigaDOS couldn't do it */
#define BREAKP SetSignal(0, 0) && SIGBREAKF_CTRL_C
/* Resource control */
#define ERROR_BUFFER 0x01
#define SOURCE_FILE 0x02
#define DESTIN_FILE 0x04
#define TERMNL_FILE 0x08
BYTEBITS resources = 0;
TEXT *errbuf; /* Pointer to current character of error file. */
TEXT *limit; /* Pointer to last byte of error file. */
TEXT *baseptr;
LONG size; /* Size of errbuf */
SHORT namlen; /* Used to skip over source file name in error file. */
LONG error = 0; /* Global error return */
TEXT editor[] = "ed "; /* Editor entered at program exit */
LONG IoErr();
BPTR src, dest, terminal, Open();
main(argc, argv)
int argc;
char *argv[];
{
TEXT srcnam[PATH_SIZE], destnam[PATH_SIZE];
TEXT cmd[PATH_SIZE + sizeof(editor)]; /* Passed to Execute() */
LONG getfile(), skip();
SHORT getname();
LONG errlin = 0; /* Line referenced by error file */
LONG srclin = 1; /* Current line of source */
if((terminal = Open("*", MODE_OLDFILE)) == NO_GO)
Exit(IoErr()); /* Panic city... */
resources |= TERMNL_FILE;
if (argc < 2) {
error = ERROR_OBJECT_NOT_FOUND;
AbnormalExit( "Usage: Error NAME\n" );
}
if(error = getfile(argv[1])) /* Reads entire error file to memory */
AbnormalExit( "Error: Can't open source file\n" );
if(skip(HEADER) == NO_MORE_LINES) /* Truly abnormal exit, yuk-yuk */
AbnormalExit( "Error: Congratulations, no compiler errors!\n");
if ((namlen = getname(srcnam, PATH_SIZE)) == 0)
AbnormalExit( "Error: Source file name error.\n");
strcpy(destnam, srcnam);
destnam[namlen - 1] = 'e';
++namlen;
cmd[0] = '\0';
strcat(cmd, editor);
strcat(cmd, destnam);
if ((src = Open(srcnam, MODE_OLDFILE)) == NO_GO) {
error = IoErr();
AbnormalExit( "Error: Can't open source file.\n");
}
resources |= SOURCE_FILE;
if ((dest = Open(destnam, MODE_NEWFILE)) == NO_GO) {
error = IoErr();
AbnormalExit( "Error: Can't open destination file.\n");
}
resources |= DESTIN_FILE;
/* Now merge the files */
while(errlin != NO_MORE_LINES || srclin != NO_MORE_LINES) {
if ( BREAKP ) /* Check for break keypress */
AbnormalExit("**BREAK\n");
errlin = get_err_lin();
srclin = copy(src, dest, srclin, errlin - 1);
errlin = copy_error(dest, srclin - 1, errlin);
}
/* Warning! AmigaDOS has a bug in the Execute function. */
/* This bug causes a small loss of memory each time Execute runs. */
cleanup(); /* Free resources */
Execute(cmd, NULL, NULL);
Exit(0);
}
AbnormalExit( what_went_wrong ) /* Also normal exit...*/
TEXT *what_went_wrong;
{
Write(terminal, what_went_wrong, strlen(what_went_wrong));
cleanup(); /* Release resources */
Exit(error);
}
cleanup() /* Release resources, but don't exit */
{
if (resources & SOURCE_FILE)
Close(src);
if (resources & DESTIN_FILE)
Close(dest);
if (resources & ERROR_BUFFER)
FreeMem(baseptr, size);
if (resources & TERMNL_FILE)
Close(terminal);
resources = 0;
}
LONG getfile(name) /* Copy error message file to memory. Return error if any */
TEXT *name;
{
struct FileLock *lock, *Lock();
struct FileInfoBlock *fib;
BPTR fh;
if ( (lock = Lock(name, ACCESS_READ)) == NO_GO)
return(IoErr());
fib = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR);
if (fib == NULL) {
UnLock(lock);
return(ERROR_NO_FREE_STORE);
}
if (Examine(lock, fib) == NO_GO) {
error = IoErr();
FreeMem(fib, sizeof(struct FileInfoBlock));
UnLock(lock);
return(error);
}
size = fib->fib_Size;
FreeMem(fib, sizeof(struct FileInfoBlock));
UnLock(lock);
if ((errbuf = (TEXT *)AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
return(ERROR_OBJECT_TOO_LARGE);
resources |= ERROR_BUFFER;
baseptr = errbuf;
if ((fh = Open(name, MODE_OLDFILE)) == NO_GO)
return(IoErr());
if (Read(fh, errbuf, size)== -1) {
error = IoErr();
Close(fh);
return(error);
}
limit = errbuf + size;
Close(fh);
return(0);
}
LONG skip(lines) /* Skip a specified number of lines in error file */
SHORT lines;
{
SHORT i = 0;
while ( i < lines)
if (*errbuf++ == '\n')
i++;
if (errbuf < limit)
return(0);
return(NO_MORE_LINES);
}
SHORT getname(name, max) /* Get file name from error file */
TEXT *name;
SHORT max;
{
SHORT i = 0;
TEXT *from = errbuf; /* Don't want to advance errbuf here */
while ( i < max && (*name++ = *from++) != ' ')
i++;
if (i < max && *--name == ' ') {
*name = '\0';
return(i);
}
/* Error return should probably be ERROR_BAD_STREAM_NAME, but this
* appears to be incorrectly assigned in the dos.h file. Fault returns
* Invalid window description for the error code assigned to
* bad stream name. */
error = ERROR_INVALID_COMPONENT_NAME;
return(0);
}
LONG get_err_lin() /* Return number of error line, or NO_MORE_LINES */
{
LONG atol(), i = 0;
errbuf += namlen; /* Move past filename at start of line */
if (errbuf >= limit || (i = atol(errbuf)) == 0)
i = NO_MORE_LINES;
return(i);
}
copy(from, to, start, end) /* Copy from srcfile to destin file */
BPTR from, to;
LONG start, end; /* Starting line, ending line */
{
TEXT tempbuf[512], *tb;
LONG what_we_got, lc;
SHORT count = 0;
if (start == NO_MORE_LINES)
return(start);
if (end == REST) {
while((what_we_got = Read(from, tempbuf, 512)) != 0) {
if (what_we_got == -1)
read_error();
if( Write(to, tempbuf, what_we_got) == -1)
write_error();
}
return(NO_MORE_LINES);
}
else {
for (lc = start; lc <= end && lc != NO_MORE_LINES; lc++ ) {
tb = tempbuf;
if ( BREAKP )
AbnormalExit( "**BREAK\n");
for(count = 0; count < 512; count++) {
if ((what_we_got = Read(from, tb++, 1)) != 1) {
if (what_we_got == 0) {
lc = NO_MORE_LINES - 1;
break;
}
else
read_error();
}
if ( *(tb - 1) == '\n')
break; /* Got one line */
}
if (Write(to, tempbuf, count + 1) == -1)
write_error();
}
}
return(lc);
}
copy_error(to, srcflg, errflg) /* Copy lines from errbuf to to */
BPTR to;
LONG srcflg, errflg;
{
REGISTER TEXT *eb = errbuf;
if (errflg == NO_MORE_LINES)
return(errflg);
while ( *eb++ < '@' && eb < limit) /* Skip line number. */
;
if (eb-- >= limit)
return(NO_MORE_LINES);
if(Write(to, "/* ***", 6) == -1)
write_error();
if (srcflg == REST) {
if ( Write(to, eb, limit - eb) == -1)
write_error();
eb = limit;
}
else {
while(*eb != '\n' && eb < limit)
if (Write(to, eb++, 1) == -1)
write_error();
}
errbuf = ++eb;
if (Write(to, " */\n", 4) == -1)
write_error();
if (errbuf >= limit)
return(NO_MORE_LINES);
return(errflg);
}
write_error() /* Report that a write error occurred. */
{
error = IoErr();
AbnormalExit( "Error: Error on write.\n");
}
read_error() /* Report that a read error occurred. */
{
error = IoErr();
AbnormalExit( "Error: Error on read.\n");
}